<template>
    <div class="page set_up">
        <h3 class="page_title" >setup</h3>
            <hr/>
            <p class="the_title" >
                1、setup?
            </p>
            <div>
                <p>在vue2之前，我们习惯性写这样的一套</p>
                <img class="v_2" src="../../assets/img/vue2.png" alt="">
                <p>
                    这种叫做 <b>选项式api</b>，尽管我们可以采用 mixin 等技术抽离部分公共代码，但是项目大了，还是看起臃肿，不易于维护。
                </p>
                <p class="marked" > 于是，在vue3中 提出了 setup 组合式api。</p>
                <p>
                    在官网的例子中，可以看到，在处理显示用户仓库显示逻辑时，<br/>
                    使用 setup 将查询（根据用户不同）、搜索、筛选 拆分为几个模块，最后一并导入 setup 中，其实个人感觉有点 mixin 那味了。<br/>
                </p>
                <p>
                    在使用 setup 拆分单独模块函数时，可以发现使用了 ref 来建立响应式数据，onMounted、watch 等钩子来保证在组件中正确的执行顺序和监听。<br/>
                    结合文档所述，setup ，可以理解为 beforeCreate 和 created 的结合（围绕 beforeCreate 和 created 生命周期钩子运行的）。<br/>
                    同时，还提供了一些 对应组件的钩子函数 <b>（选项式钩子函数 前面加 on 前缀）</b>
                </p>
            </div>
            <div class="marked" style="padding:10px 0" >
                个人感觉，setup 组合式api就是让我们更加轻松的去拆分组件，而不再是以前 固定的导入一堆，在 setup 后面继续使用以前套路，当然也是可以的 
            </div>
            <hr/>
            <h3 class="the_title" >
                2、测试一下结合ts
            </h3>
            <p>
               配合 ts 我们使用 defineComponent，更好的在 setup 中进行类型推论。
            </p>

            <h4>
                 <b>2.1 setup 数据、监听、计算属性</b>
            </h4>
            <div class="placeholder" ></div>
            <p>
                这是一个通过 <b>ref</b> 建立的布尔值 {{refData}}
                <button @click="changeRefData" > 点击改变 </button> <br/>
                <b>
                    通过 ref 建立的响应式数据，值要这样获取 xxx.value
                </b>
            </p>
            <div class="placeholder" ></div>
            <p>
                这是一个通过 <b>reactive</b> 建立的对象 {{`age：${recData.age}，name：${recData.name}`}} <br/>
                <b> 计算属性 反转名字 {{reverseName}} </b> <br/>
                通过 reactive 建立出来的格式为 xxx.age 和 xxx.name，要想直接展示 age 和 name 可以使用 toRefs<br/>
                在返回时 结构一下 ...toRefs(xxx)
            </p>
            <p>
                <b> watch 使用，查看控制台</b>，同样可以设置 立即监听，深度监听啥的
            </p>
            <h3 class="the_title" >
                3、使用 setup 来拆分
            </h3>
            <div>
                <p>将数据的获取，抽出到单独的js文件中，然后导入 setup 中</p>
                <ul>
                    <li v-for="( item ) in shopList" :key="item.id" >
                        {{`商品名称：${item.name}   价格：${item.price}`}}
                        <button @click="deletShop(item.id)" >删除</button>
                        <button>修改商品价格</button>
                    </li>
                </ul>
                <p> 增删改查就不一一实现了，大概就是这么回事儿 </p>
            </div>
            <h3 class="the_title" >
                4、简单总结
            </h3>
            <p>
                setup 感觉是可以用来分割以前 v2 模式写的那些东西， <br/>
                setup 中没有 this ，因此也不能访问 data、methods ，写的东西也要 return 出去才有用<br/>
                在返回数据时，最好辨别是不是响应式，避免出现页面无响应( 解构赋值时要多注意了 )<br/>
                可能正是因为这样，vue 才提供了 鉴别数据是不是响应式的 api 吧
            </p>
        <div style="height:20vh" ></div>
    </div>
</template>

<script lang="ts">
import { defineComponent,reactive,ref,computed,watch,onMounted } from "vue";
import { getData } from './dataHandle';

// 这里就不单独写了
interface Peson {
    age: number | string;
    name: string;
}

export default defineComponent({
    name: "Setup",
    setup() {
        // 数据
        const refData = ref<boolean>(false)
        const recData = reactive<Peson>({
            age:22,
            name:'琦玉老师'
        })
     
        const shopList = getData()
 
        const changeRefData = (): void => {
            refData.value = !refData.value
        }
        // setup 中处理
        const deletShop =  (id: number | string): void => {
            shopList.value = shopList.value.filter((item) => {
                return item.id != id
            })
        }

        const reverseName = computed( (): string => {
            return recData.name.split('').reverse().join()
        })

        watch(refData,
            (count,prevCount): void =>{
                console.log('当前值-----',count)
                console.log('以前值-----',prevCount)
            },
            { immediate: true,deep: true }
        )

        onMounted( (): void => {
            console.log(`onMounted：`,recData)
        })
        return {
            refData,
            recData,
            shopList,
            reverseName,
            changeRefData,
            deletShop
        }
    },
    // 任然可以使用 v2 的模式
    data() {
        return {
            list:[1,2,3,4,4]
        }
    },
    mounted(){
        console.log(`mounted：this`,this)
    },
    methods:{
        // 在 v2 中处理

        // deletShop(id: number | string): void {
        //     this.shopList = this.shopList.filter((item) => {
        //         return item.id != id
        //     })
        // }
    }
})
</script>

<style lang="less" scoped>
    // @import '~../../assets/css/tit_public.less';
    .set_up{
        .v_2{
            width: 60%;
        }
        ul{
            li{
                padding: 10px 0;
                button{
                    margin-left: 10px;
                }
            }
        }
    }
</style>
